package main

import (
	"fmt"
	"net"
)

type User struct {
	Name string
	Addr string
	C    chan string // 用户channel，可以获取消息和发送消息
	conn net.Conn

	server *Server //为了让User跟该Server产生关联                                ↓↓↓
}

// 创建一个用户API
func NewUser(conn net.Conn, server *Server) *User {

	userAddr := conn.RemoteAddr().String()

	// 初始化User对象
	user := &User{
		Name:   userAddr,
		Addr:   userAddr,
		C:      make(chan string),
		conn:   conn,
		server: server,
	}

	// 创建了用户即应该启动监听当前user channel消息的goroutine
	go user.ListenMessage()

	return user
}

// 用户上线的业务方法
func (this *User) Online() {

	// 用户上线，通过map的api将用户存到OnlineMap中
	this.server.mapLock.Lock()
	this.server.OnlineMap[this.Name] = this // 给User添加Server属性的体现在这里
	this.server.mapLock.Unlock()

	// 调用broad接口广播当前用户消息给其他用户知道
	this.server.BroadCast(this, "has been lanuched")
}

// 用户下线的业务方法
func (this *User) Offline() {
	// 用户上线，通过map的api将用户存到OnlineMap中
	this.server.mapLock.Lock()
	delete(this.server.OnlineMap, this.Name)
	this.server.mapLock.Unlock()

	// 调用broad接口广播当前用户消息给其他用户知道
	this.server.BroadCast(this, "has been disconnected")
}

// 发送在线消息
func (this *User) SendMsg(msg string) {
	_, err := this.conn.Write([]byte(msg))
	if err != nil {
		fmt.Println("发送在线消息失败")
	}
}

// 用户处理消息的业务方法
func (this *User) DoMessage(msg string) {
	// v5：当用户想查询在线的User发送请求指令who
	if msg == "who" {
		this.server.mapLock.Lock()
		for _, user := range this.server.OnlineMap {
			onlineMsg := "[" + user.Addr + "]" + user.Name + ":" + "online..\n"
			this.SendMsg(onlineMsg)
		}
		this.server.mapLock.Unlock()
	} else {
		this.server.BroadCast(this, msg)
	}
}

// 创建一个方法监听当前User的channel通道，获取信息
func (this *User) ListenMessage() {
	// 采用死循环不断监听
	for {
		msg := <-this.C
		// 以字节数组的形式将消息写出到连接里
		this.conn.Write([]byte(msg + "\n"))

	}

}
